package com.eastfair.questionnaire.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.enums.SystemSourceEnum;
import com.eastfair.projectcore.api.ProjectCoreServiceFeign;
import com.eastfair.core.snowflake.DefaultUidGenerator;
import com.eastfair.questionnaire.dao.QuestionnaireRelationMapper;
import com.eastfair.questionnaire.entity.QuestionnaireRelation;
import com.eastfair.questionnaire.enums.QuestionnaireRelationTypeEnum;
import com.eastfair.questionnaire.service.QuestionnaireRelationService;
import com.eastfair.questionnaire.vo.QuestionnaireRelationVO;
import com.google.common.collect.Lists;
import javafx.util.Pair;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 问卷外部系统映射关系
 * </p>
 *
 * @author yuwx
 * @date 2021-08-18
 */
@Slf4j
@Service
public class QuestionnaireRelationServiceImpl extends SuperServiceImpl<QuestionnaireRelationMapper, QuestionnaireRelation> implements QuestionnaireRelationService {
    private ProjectCoreServiceFeign projectCoreServiceFeign;

    @Autowired
    public QuestionnaireRelationServiceImpl(ProjectCoreServiceFeign projectCoreServiceFeign) {
        this.projectCoreServiceFeign = projectCoreServiceFeign;
    }

    /**************sharding 分库分表操作 *****************/
    @Override
    public boolean updateByIdOfShard(QuestionnaireRelation entity) {
        UpdateWrapper<QuestionnaireRelation> updateWrapper = new UpdateWrapper<>();
        //可将指定字段更新为null
        updateWrapper.lambda().eq(QuestionnaireRelation::getProjectId, entity.getProjectId()).eq(QuestionnaireRelation::getId, entity.getId());
        entity.setProjectId(null);
        return SqlHelper.retBool(this.getBaseMapper().update(entity, updateWrapper));
    }

    /**
     * 处理新增相关处理
     *
     * @param model 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerSave(QuestionnaireRelation model) {
        //雪花ID
        model.setId(DefaultUidGenerator.getUidOfProjectId(ContextUtil.getProjectId()));
        model.setProjectId(ContextUtil.getProjectId());
        return R.successDef();
    }

    @Override
    public List<QuestionnaireRelationVO> get(Long projectId, QuestionnaireRelationTypeEnum relationTypeEnum, SystemSourceEnum systemSourceEnum, Long internalId) {
        if (Objects.isNull(projectId) || Objects.isNull(relationTypeEnum) || Objects.isNull(systemSourceEnum)) {
            throw new NullPointerException();
        }
        List<Long> selfIdList = Lists.newArrayList(internalId);
        List<QuestionnaireRelationVO> questionnaireRelationList = listByInternal(projectId, relationTypeEnum, systemSourceEnum, selfIdList);
        return questionnaireRelationList;
    }

    @Override
    public List<QuestionnaireRelationVO> listByInternal(Long projectId, QuestionnaireRelationTypeEnum relationTypeEnum, SystemSourceEnum systemSourceEnum, List<Long> internalIdList) {
        if (Objects.isNull(projectId) || Objects.isNull(relationTypeEnum) || Objects.isNull(systemSourceEnum)) {
            throw new NullPointerException();
        }
        if (CollectionUtil.isEmpty(internalIdList)) {
            return Collections.emptyList();
        }
        QueryWrapper<QuestionnaireRelation> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(QuestionnaireRelation::getProjectId, projectId)
                .eq(QuestionnaireRelation::getRelationType, relationTypeEnum)
                .eq(QuestionnaireRelation::getExternalSourceSystem, systemSourceEnum)
                .eq(QuestionnaireRelation::getIsEnable, BusinessConstant.YES)
                .eq(QuestionnaireRelation::getIsDelete, BusinessConstant.NO)
                .in(QuestionnaireRelation::getSelfId, internalIdList);
        List<QuestionnaireRelation> questionnaireRelationList = list(queryWrapper);
        if (CollectionUtil.isEmpty(questionnaireRelationList)) {
            return Collections.emptyList();
        }
        return ConvertUtil.convertList(questionnaireRelationList, QuestionnaireRelationVO.class);
    }

    @Override
    public List<QuestionnaireRelationVO> listByExternal(Long projectId, QuestionnaireRelationTypeEnum relationTypeEnum, SystemSourceEnum systemSourceEnum, List<String> externalIdList) {
        if (Objects.isNull(projectId) || Objects.isNull(relationTypeEnum) || Objects.isNull(systemSourceEnum)) {
            throw new NullPointerException();
        }
        if (CollectionUtil.isEmpty(externalIdList)) {
            return Collections.emptyList();
        }
        QueryWrapper<QuestionnaireRelation> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(QuestionnaireRelation::getProjectId, projectId)
                .eq(QuestionnaireRelation::getRelationType, relationTypeEnum)
                .eq(QuestionnaireRelation::getExternalSourceSystem, systemSourceEnum)
                .eq(QuestionnaireRelation::getIsEnable, BusinessConstant.YES)
                .eq(QuestionnaireRelation::getIsDelete, BusinessConstant.NO)
                .in(QuestionnaireRelation::getExternalId, externalIdList);
        List<QuestionnaireRelation> questionnaireRelationList = list(queryWrapper);
        if (CollectionUtil.isEmpty(questionnaireRelationList)) {
            return Collections.emptyList();
        }
        return ConvertUtil.convertList(questionnaireRelationList, QuestionnaireRelationVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(Long projectId, QuestionnaireRelationTypeEnum relationTypeEnum, SystemSourceEnum systemSourceEnum, List<Pair<Long, String>> pairList) {
        if (Objects.isNull(projectId) || Objects.isNull(relationTypeEnum) || Objects.isNull(systemSourceEnum)) {
            throw new NullPointerException();
        }
        if (CollectionUtil.isEmpty(pairList)) {
            return;
        }
        List<QuestionnaireRelation> questionnaireRelationList = pairList.stream()
                .filter(pair -> !Objects.isNull(pair) && !Objects.isNull(pair.getKey()))
                .map(pair -> {
                    QuestionnaireRelation questionnaireRelation = QuestionnaireRelation.builder()
                            .id(DefaultUidGenerator.getUidOfProjectId(projectId))
                            .projectId(projectId)
                            .selfId(pair.getKey())
                            .externalId(pair.getValue())
                            .relationType(relationTypeEnum.getValue())
                            .externalSourceSystem(systemSourceEnum.getValue()).build();
                    return questionnaireRelation;
                }).collect(Collectors.toList());
        List<Long> selfIdList = questionnaireRelationList.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(n -> n.getSelfId()))), ArrayList::new))
                .stream().map(q -> q.getSelfId()).collect(Collectors.toList());
        //先删除
        delete(projectId, relationTypeEnum, systemSourceEnum, selfIdList);
        //再插入
        saveBatch(questionnaireRelationList);
    }

    @Override
    public void delete(Long projectId, QuestionnaireRelationTypeEnum relationTypeEnum, SystemSourceEnum systemSourceEnum, List<Long> internalIdList) {
        UpdateWrapper<QuestionnaireRelation> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(QuestionnaireRelation::getProjectId, projectId)
                .eq(QuestionnaireRelation::getRelationType, relationTypeEnum)
                .eq(QuestionnaireRelation::getExternalSourceSystem, systemSourceEnum)
                .in(QuestionnaireRelation::getSelfId, internalIdList);
        QuestionnaireRelation delete = QuestionnaireRelation.builder().isDelete(BusinessConstant.YES).build();
        SqlHelper.retBool(this.getBaseMapper().update(delete, updateWrapper));
    }


}
